package com.example.usercenter.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.usercenter.enums.StatusEnum;
import com.example.usercenter.exception.BusinessException;
import com.example.usercenter.model.request.UserSearchRequest;
import com.example.usercenter.service.UserService;
import com.example.usercenter.model.domain.User;
import com.example.usercenter.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.example.usercenter.constant.UserConstant.USER_LOGIN_STATUS;

/**
 * @author 86138
 * @description 针对表【user】的数据库操作Service实现
 * @createDate 2024-08-26 14:35:32
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {


    //加密盐
    private static final String SALT = "hhf";

    @Override
    public long register(String account, String password, String checkPassword) {

        //1.账号密码校验
        if (StringUtils.isAnyBlank(account, password, checkPassword)) {
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "参数错误");
        }

        if (account.length() < 4 || password.length() < 8) {
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "账号密码不符合规范");
        }

        //3.账号不包含特殊字符
        String checkValid = "[!@#$%^&*()]";
        Matcher matcher = Pattern.compile(checkValid).matcher(account);
        if (matcher.find()) {
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "账号包含特殊字符");
        }

        //4.密码与重复密码一致
        if (!password.equals(checkPassword)) {
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "密码与校验密码不一致");
        }

        //2.账号是否重复(少进行一次数据库操作)
        boolean exists = this.lambdaQuery().eq(User::getAccount, account).exists();
        if (exists) {
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "账号已存在");
        }

        //5.密码加密
        String encryptPassword = encryptedPassword(password);

        //6.插入数据库
        User user = new User();
        user.setAccount(account);
        user.setPassword(encryptPassword);
        boolean save = this.save(user);

        if (!save) {
            throw new BusinessException(StatusEnum.SYSTEM_ERROR);
        }
        return user.getId();
    }

    @Override
    public User login(String account, String password, HttpServletRequest request) {

        //1.校验用户名和密码
        if (StringUtils.isAnyBlank(account, password) || account.length() < 4 || password.length() < 8) {
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "账号密码不符合规范");
        }
        //2.密码比对
        User originUser = this.lambdaQuery().eq(User::getAccount, account).one();
        if (originUser == null) {
            log.info("user login failed,user cannot exist");
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "账号不存在");
        }
        if (!(encryptedPassword(password)).equals(originUser.getPassword())) {
            log.info("user login failed,user password cannot match");
            throw new BusinessException(StatusEnum.PARAMS_ERROR, "密码错误");
        }
        //3.保存登录状态
        HttpSession session = request.getSession();
        session.setAttribute(USER_LOGIN_STATUS, originUser);

        //4.用户信息脱敏
        User safetyUser = getSafetyUser(originUser);


        //5.返回用户信息
        return safetyUser;
    }

    private User getSafetyUser(User originUser) {

        if (originUser == null) {
            return null;
        }

        User handlerUser = new User();
        handlerUser.setId(originUser.getId());
        handlerUser.setUsername(originUser.getUsername());
        handlerUser.setAccount(originUser.getAccount());
        handlerUser.setGender(originUser.getGender());
        handlerUser.setAvatarUrl(originUser.getAvatarUrl());
        handlerUser.setPhone(originUser.getPhone());
        handlerUser.setEmail(originUser.getEmail());
        handlerUser.setRole(originUser.getRole());
        handlerUser.setStatus(originUser.getStatus());
        handlerUser.setCreateTime(originUser.getCreateTime());
        return handlerUser;
    }

    @Override
    public List<User> search(UserSearchRequest userSearchRequest) {


        //查询条件
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        wrapper.like(StrUtil.isNotBlank(userSearchRequest.getUsername()), User::getUsername, userSearchRequest.getUsername());
        wrapper.like(StrUtil.isNotBlank(userSearchRequest.getPhone()), User::getPhone, userSearchRequest.getPhone());
        wrapper.like(StrUtil.isNotBlank(userSearchRequest.getAccount()), User::getAccount, userSearchRequest.getAccount());
        wrapper.like(StrUtil.isNotBlank(userSearchRequest.getEmail()), User::getEmail, userSearchRequest.getEmail());
        wrapper.eq(userSearchRequest.getGender() != null, User::getGender, userSearchRequest.getGender());
        Date createTime = userSearchRequest.getCreateTime();
        if ( createTime!= null){
            DateTime start = DateUtil.beginOfDay(createTime);
            DateTime end = DateUtil.endOfDay(createTime);
            wrapper.between(User::getCreateTime,start,end);
        }
        wrapper.eq(userSearchRequest.getStatus() != null,User::getStatus, userSearchRequest.getStatus());


        //获取数据
        List<User> userList = this.list(wrapper);

        //数据脱敏
        List<User> safeUser = userList.stream().map(user -> getSafetyUser(user)).collect(Collectors.toList());

        return safeUser;
    }

    @Override
    public User getCurrentUser(HttpServletRequest request) {

        //1.从session中取出凭证
        HttpSession session = request.getSession();
        Object userObj = session.getAttribute(USER_LOGIN_STATUS);
        User user = (User) userObj;
        if (user == null) {
            throw new BusinessException(StatusEnum.NO_LOGIN);
        }
        //2.查询数据库,获取用户信息
        User currentUser = this.getById(user.getId());

        //3.脱敏返回数据
        User safetyUser = this.getSafetyUser(currentUser);
        return safetyUser;

    }

    @Override
    public void logout(HttpServletRequest request) {

        //1.重新设置session的值
        HttpSession session = request.getSession();

        session.removeAttribute(USER_LOGIN_STATUS);

    }


    /**
     * 密码加密
     *
     * @param password
     * @return
     */
    private String encryptedPassword(String password) {

        //现在暂时先用spring自带的加密算法
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + password).getBytes());

        return encryptPassword;
    }
}




